<?php declare(strict_types=1);

namespace App\Http\Business\Admin;

use App\Model\SystemUser;
use App\Model\SystemUserRole;
use Swoft\Redis\Redis;

/**
 * 后台用户-业务类
 * Class AdminUserBusiness
 * @package App\Http\Business\Admin
 */
class SystemUserBusiness
{
        /**
         * 登录
         * @return array|int[]
         * @throws \Exception
         */
        public static function login(): array
        {
                $arrParam = post();
                $strUsername = strAddslashes($arrParam['username']);
                $strPassword = strAddslashes($arrParam['password']);
                $strCaptcha = strAddslashes($arrParam['captcha']);
                $strKey = strAddslashes($arrParam['key']);
                $arrWhere = ['username' => $strUsername];
                $arrField = ['userId', 'realName', 'avatar', 'username', 'password', 'salt', 'status', 'updateTime'];
                $arrData = SystemUser::getOne($arrWhere, $arrField);
                if (!$arrData) throw new \Exception('账户名或密码错误');
                if ($arrData['password'] != md5(md5($strPassword) . $arrData['salt'])) throw new \Exception('账户名或密码错误');
                if ($arrData['status'] != 1) throw new \Exception('您已被禁止登录，如有疑问请联系管理员');
                $strCheckCaptcha = Redis::get($strKey . 'OperationCaptcha');
                if ($strCheckCaptcha === false || $strCaptcha !== $strCheckCaptcha) throw new \Exception('验证码错误');
                $arrWhere = ['userId' => $arrData['userId']];
                $arrSet = ['lastTime' => request()->timestamp, 'lastIp' => ip()];
                SystemUser::renewal($arrWhere, $arrSet);
                $arrEncryptData = [
                        'userId' => $arrData['userId'],
                        'updateTime' => $arrData['updateTime'],
                        'lastTime' => request()->timestamp
                ];
                $jsonEncryptData = json_encode($arrEncryptData, JSON_UNESCAPED_UNICODE);
                $strToken = encryptOpenssl($jsonEncryptData, SSL_KEY, SSL_IV);
                $arrResponseData = [
                        'token' => $strToken,
                        'user' => [
                                'realName' => $arrData['realName'],
                                'avatar' => getDomain() . $arrData['avatar'],
                                'username' => $arrData['username'],
                                'position' => []
                        ]
                ];
                $strMsg = getHello() . '，欢迎回来';
                return callbackParam(0, true, $arrResponseData, $strMsg);
        }

        /**
         * 查询用户
         * @param string $userId
         * @return array
         */
        public static function query(string $userId): array
        {
                if ($userId) {
                        $arrField = ['userId', 'realName', 'phone', 'username', 'status', 'avatar'];
                        $arrResult = SystemUser::primaryKeyFind(strAddslashes($userId), $arrField);
                        if (isset($arrResult['avatar'])) $arrResult['avatar'] = getDomain() . $arrResult['avatar'];
                        $arrResult['roleIds'] = SystemUserRole::getColumn(['userId' => strAddslashes($userId)], 'roleId');
                        return callbackParam(0, true, $arrResult);
                } else {
                        $arrParam = get();
                        if (isset($arrParam['queryType']) && $arrParam['queryType'] == 1) {//选项查询全部用户
                                $arrField = ['userId', 'realName', 'phone', 'username'];
                                $arrResult = SystemUser::getAll([], $arrField);
                                return callbackParam(0, true, $arrResult);
                        }
                        $intPage = intval(issetArrKey($arrParam, 'page', 1));
                        $intLimit = intval(issetArrKey($arrParam, 'limit', 10));
                        $arrWhere = [];
                        if (isset($arrParam['realName']) && $arrParam['realName']) $arrWhere[] = ['realName', 'like', "%{$arrParam['realName']}%"];
                        if (isset($arrParam['phone']) && $arrParam['phone']) $arrWhere[] = ['phone', 'like', "%{$arrParam['phone']}%"];
                        if (isset($arrParam['username']) && $arrParam['username']) $arrWhere[] = ['username', 'like', "%{$arrParam['username']}%"];
                        if (isset($arrParam['createTime']) && $arrParam['createTime']) $arrWhere[] = ['whereBetween', 'createTime', array_map('strtotime', $arrParam['createTime'])];
                        if (isset($arrParam['updateTime']) && $arrParam['updateTime']) $arrWhere[] = ['whereBetween', 'updateTime', array_map('strtotime', $arrParam['updateTime'])];
                        if (isset($arrParam['lastTime']) && $arrParam['lastTime']) $arrWhere[] = ['whereBetween', 'lastTime', array_map('strtotime', $arrParam['lastTime'])];
                        if (isset($arrParam['lastIp']) && $arrParam['lastIp']) $arrWhere[] = ['lastIp', 'like', "%{$arrParam['lastIp']}%"];
                        if (isset($arrParam['status']) && $arrParam['status']) $arrWhere['status'] = intval($arrParam['status']);
                        $arrField = ['system_user.userId', 'avatar', 'realName', 'phone', 'username', 'status', 'createTime', 'updateTime', 'lastTime', 'lastIp'];
                        $arrJoin = [];
                        $arrGroupBy = [];
                        if (isset($arrParam['roleIds']) && $arrParam['roleIds']) {
                                $arrJoin['system_user_role'] = [
                                        'table' => 'system_user_role',
                                        'where' => ['system_user_role.userId', '=', 'system_user.userId']
                                ];
                                $arrWhere[] = ['whereIn', 'roleId', strAddslashes($arrParam['roleIds'])];
                                $arrGroupBy = ['system_user_role.userId'];
                        }
                        $arrResult = SystemUser::getList($arrWhere, $arrField, $intPage, $intLimit, [], $arrGroupBy, $arrJoin);
                        $arrUserId = array_column($arrResult['list'], 'userId');
                        $arrWhere = [['whereIn', 'userId', $arrUserId]];
                        $arrUserRole = arrayGroupBy(SystemUserRole::getAll($arrWhere, ['userId', 'roleId']), 'userId');
                        foreach ($arrResult['list'] as $k => $v) {
                                $arrResult['list'][$k]['avatar'] = getDomain() . $v['avatar'];
                                $arrTempUserRole = array_column(issetArrKey($arrUserRole, $v['userId'], []), 'roleId');
                                $arrResult['list'][$k]['roleIds'] = $arrTempUserRole;
                        }
                        $arrResult['page'] = $intPage;
                        $arrResult['limit'] = $intLimit;
                        return callbackParam(0, true, $arrResult);
                }
        }

        /**
         * 新增用户
         * @return array
         * @throws \Exception
         */
        public static function add(): array
        {
                $arrParam = post();
                $strUserId = uuid();
                $strSalt = mt_rand(1000, 9999);
                $strPhone = strAddslashes($arrParam['phone']);
                $strUsername = strAddslashes($arrParam['username']);
                $strCheckPhone = SystemUser::getFieldValue(['phone' => $strPhone], 'userId');
                if ($strCheckPhone) throw new \Exception('手机号已存在');
                $strCheckUsername = SystemUser::getFieldValue(['username' => $strUsername], 'userId');
                if ($strCheckUsername) throw new \Exception('用户名已存在');
                $arrSet = [
                        'userId' => $strUserId,
                        'avatar' => strAddslashes(strstr($arrParam['avatar'], '/public/uploads/pic/')),
                        'realName' => strAddslashes($arrParam['realName']),
                        'phone' => $strPhone,
                        'username' => $strUsername,
                        'password' => md5(md5(strAddslashes($arrParam['password'])) . $strSalt),
                        'salt' => $strSalt,
                        'status' => intval($arrParam['status']),
                        'createTime' => request()->timestamp
                ];
                $arrRoleIds = $arrParam['roleIds'];
                $arrUserRoleSet = [];
                foreach ($arrRoleIds as $v) {
                        $arrUserRoleSet[] = [
                                'userId' => $strUserId,
                                'roleId' => strAddslashes($v)
                        ];
                }
                $bool = SystemUser::insert($arrSet);
                if (!$bool) throw new \Exception('服务器处理数据失败');
                SystemUserRole::insert($arrUserRoleSet);
                $arrSet['roleIds'] = $arrRoleIds;
                $arrSystemLogData = ['behavior' => '新增用户', 'operationAfter' => $arrSet];
                setSystemLog($arrSystemLogData);
                $arrResult = ['userId' => $strUserId];
                return callbackParam(0, true, $arrResult, '新增成功');
        }

        /**
         * 编辑用户
         * @param string $userId
         * @return array
         * @throws \Exception
         */
        public static function edit(string $userId): array
        {
                $arrParam = post();
                $arrOperationBefore = self::query($userId)['data'];
                if (!$arrOperationBefore) throw new \Exception('数据不存在');
                $strUserId = strAddslashes($userId);
                if ($strUserId == 'lcl00000004-0819-e715-a6cf-dcf0210560ae') throw new \Exception('禁止编辑管理员');
                $strPhone = strAddslashes($arrParam['phone']);
                $strUsername = strAddslashes($arrParam['username']);
                $strCheckPhone = SystemUser::getFieldValue(['phone' => $strPhone], 'userId');
                if ($strCheckPhone && $strCheckPhone != $strUserId) throw new \Exception('手机号已存在');
                $strCheckUsername = SystemUser::getFieldValue(['username' => $strUsername], 'userId');
                if ($strCheckUsername && $strCheckUsername != $strUserId) throw new \Exception('用户名已存在');
                $arrSet = [
                        'userId' => $strUserId,
                        'avatar' => strAddslashes(strstr($arrParam['avatar'], '/public/uploads/pic/')),
                        'realName' => strAddslashes($arrParam['realName']),
                        'phone' => $strPhone,
                        'username' => $strUsername,
                        'status' => intval($arrParam['status']),
                        'updateTime' => request()->timestamp
                ];
                if (isset($arrParam['password']) && $arrParam['password']) {
                        if (mb_strlen($arrParam['password']) < 3 || mb_strlen($arrParam['password']) > 30){
                                throw new \Exception('password is invalid length(min=3, max=30)');
                        }
                        $strSalt = mt_rand(1000, 9999);
                        $arrSet['password'] = md5(md5(strAddslashes($arrParam['password'])) . $strSalt);
                        $arrSet['salt'] = $strSalt;
                }
                $arrRoleIds = $arrParam['roleIds'];
                $arrUserRoleSet = [];
                foreach ($arrRoleIds as $v) {
                        $arrUserRoleSet[] = [
                                'userId' => $strUserId,
                                'roleId' => strAddslashes($v)
                        ];
                }
                $arrWhere = ['userId' => $strUserId];
                $bool = SystemUser::renewal($arrWhere, $arrSet);
                if (!$bool) throw new \Exception('服务器处理数据失败');
                SystemUserRole::remove($arrWhere);
                SystemUserRole::insert($arrUserRoleSet);
                $arrSet['roleIds'] = $arrRoleIds;
                $arrSystemLogData = ['behavior' => '编辑用户', 'operationBefore' => $arrOperationBefore, 'operationAfter' => $arrSet, 'whereData' => $arrWhere];
                setSystemLog($arrSystemLogData);
                return callbackParam(0, true, [], '编辑成功');
        }

        /**
         * 编辑指定字段
         * @param string $userId
         * @param string $field
         * @return array
         * @throws \Exception
         */
        public static function editSpecifiedField(string $userId, string $field): array
        {
                $strUserId = strAddslashes($userId);
                if ($strUserId == 'lcl00000004-0819-e715-a6cf-dcf0210560ae') throw new \Exception('禁止编辑管理员');
                $arrOperationBefore = SystemUser::primaryKeyFind($strUserId, [strAddslashes($field)]);
                if (!$arrOperationBefore) throw new \Exception('数据不存在');
                switch ($field) {
                        case 'status':
                                $arrSet = ['status' => intval(post('status'))];
                                break;
                        default :
                                throw new \Exception('未知字段');
                }
                $arrWhere = ['userId' => $strUserId];
                $arrSet['updateTime'] = request()->timestamp;
                $bool = SystemUser::renewal($arrWhere, $arrSet);
                if (!$bool) throw new \Exception('服务器处理数据失败');
                $arrSystemLogData = ['behavior' => '编辑用户指定字段', 'operationBefore' => $arrOperationBefore, 'operationAfter' => $arrSet, 'whereData' => $arrWhere];
                setSystemLog($arrSystemLogData);
                return callbackParam(0, true, [], '编辑成功');
        }
}